package joSaysHello.client;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import joSaysHello.client.gui.HelloList;
import joSaysHello.client.gui.ServerReplyDlg;
import joSaysHello.shared.entity.Hello;
import joSaysHello.shared.entity.User;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class JoSaysHello implements EntryPoint {

	/**
	 * Create a remote service proxy to talk to the server-side Greeting service.
	 */
	private final GreetingServiceAsync greet = GWT.create(GreetingService.class);
	private final UserMgmtServiceAsync userMgmt = GWT.create(UserMgmtService.class);
	private User user = null;

	final HTML loggedIn = new HTML();
	final Button logInOut = new Button();
	final Button sendButton = new Button("Say Hello!");
	
	final List<Hello> hellos = new ArrayList<Hello>();
	final HelloList helloList = new HelloList();
	
	final ServerReplyDlg helloDlg = new ServerReplyDlg();
	//final LoginDlg loginDlg = new LoginDlg(userMgmt);
	
	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		HorizontalPanel loginPanel = new HorizontalPanel();
		Label openIdLabel = new Label("This page uses the Google OpenID:", true); 
		loginPanel.add(openIdLabel);
		loginPanel.add(logInOut);
		loginPanel.setSpacing(10);
		loginPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
		loginPanel.setCellVerticalAlignment(openIdLabel, HasVerticalAlignment.ALIGN_MIDDLE);
		//loginPanel.setBorderWidth(2);
		loggedIn.setVisible(false);
		logInOut.setVisible(false);
		logInOut.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				if(user == null)
					login();
				else
				{
					logout();
				}	
			}});
		//setUser(null);

		// We can add style names to widgets
		sendButton.addStyleName("sendButton");
		sendButton.setEnabled(false);

		VerticalPanel gui = new VerticalPanel();
		gui.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		gui.addStyleName("approot");
		Label header = new Label("Jo says Hello!");
		header.addStyleName("header");
		gui.add(header);
		gui.add(loggedIn);
		gui.add(loginPanel);
		gui.add(sendButton);
		gui.add(new HTML("<hr width='400' />"));
		helloList.setRowData(hellos);
		helloList.setEmptyListMessage(SafeHtmlUtils.fromString("nobody said hello yet. be the first!"));
		helloList.setVisible(false);
		helloList.addStyleName("helloList");
		gui.add(helloList);
		RootPanel.get("jo-says-hello").add(gui);

		sendButton.setFocus(true);

		// Add a handler to close the DialogBox
		helloDlg.addCloseHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				sendButton.setEnabled(true);
				sendButton.setFocus(true);
			}
		});
		
		/*
		loginDlg.addCloseHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				updateUser();
			}
			
		});
		*/
		
		sendButton.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				sendButton.setEnabled(false);
				greet.sayHello(new AsyncCallback<Hello>() {
					public void onFailure(Throwable caught) {
						helloDlg.showServerError(caught);
						sendButton.setEnabled(true);
					}
					public void onSuccess(Hello result) {
						helloDlg.showServerReply(result);
						updateHellos();
						sendButton.setEnabled(true);
					}
				});
			}});
		//nameField.addKeyUpHandler(handler);
		
		updateUser();
		
		updateHellos();
	}
	
	private static final String openIdUrl = "www.google.com/accounts/o8/id";
	private static final AsyncCallback<String> redirectorCallback = new AsyncCallback<String>()
	{
		public void onFailure(Throwable caught) {
			Window.alert(caught.getMessage());
		}
		public void onSuccess(String url) {
			Window.open(url, "_self", "");
		}
	};
	private void login()
	{
		userMgmt.getLoginURL(openIdUrl, Window.Location.getHref(), redirectorCallback);
	}
	private void logout()
	{
		userMgmt.getLogoutURL(Window.Location.getHref(), redirectorCallback);
	}
	
	private void updateUser()
	{
		userMgmt.getUser(new AsyncCallback<User>() {

			@Override
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());
			}

			@Override
			public void onSuccess(User user) {
				setUser(user);
			}});
	}
	private void setUser(User user)
	{
		this.user = user;
		if(user == null)
		{
			loggedIn.setHTML("You are <b>not</b> logged in.");
			logInOut.setText("Google OpenID login / sign-on");
		}
		else
		{
			loggedIn.setHTML("You are logged in as <b>"+user+"</b>.");
			logInOut.setText("Google OpenID logout");
		}
		sendButton.setEnabled(user != null);
		loggedIn.setVisible(true);
		logInOut.setVisible(true);
	}
	
	private void updateHellos()
	{
		Date since = (hellos.isEmpty() ? null : hellos.get(0).getWhen());
		greet.getHellosSince(since, new AsyncCallback<List<Hello>>() {
			public void onFailure(Throwable caught) {
				Window.alert(caught.getMessage());
			}
			public void onSuccess(List<Hello> result) {
				hellos.addAll(0, result);
				helloList.setRowData(hellos);
				helloList.setVisible(true);
			}});
	}
	
}
